package cn.edu.sjtu.se.dslab.component.aadl;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.dom4j.Document;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import cn.edu.sjtu.se.dslab.component.aadl.AAXLElement.AAXLConnection;
import cn.edu.sjtu.se.dslab.component.aadl.AAXLElement.AAXLFeature;
import cn.edu.sjtu.se.dslab.component.aadl.AAXLElement.AAXLSubComponent;

/**
 * aaxl解析类service
 * @author sunke
 *
 */
@Service("aaxlParser")
@Transactional
public class AAXLParser {
	
	private final static String CORE = "core:AadlSpec";
	
	//project name
	private final static String NAME = "name";
	
	private final static String XMI_VERSION = "xmi:version";
	
	private final static String XMLNS_XMI ="xmlns:xmi";
	
	private final static String XMLNS_XSI = "xmlns:xsi";
	
	private final static String XMLNS_CORE = "xmlns:core";
	
	private final static String XMLNS_PROPERTY = "xmlns:property";
	//impl对应的type
	private final static String  COMP_TYPE ="compType";
	
	private final static String CONNECTIOINS = "connections";
	
	
	private final static String DST_CONTEXT = "dstContext";
	
	private final static String SRC_CONTEXT = "srcContext";
	
	private final static String SRC = "src";
	
	private final static String DST ="dst";
	
	private final static String SUB_COMPONENTS = "subcomponents";
	
	
	private final static String CLASSIFIER = "classifier";
	
	private final static String FEATURES = "features";
	
	private final static String BUS_ACCESS = "busAccess";
	
	private final static String DATA_PORT = "dataPort";
	
	private final static String DIRECTION_OUT = "OUT";
	
	private final static String DIRECTION_IN = "in";
	
	private final static String REQUIRED ="required";
	
	private final static String DIRECTION ="direction";
/////////////////////////////////////////////////////////////////////////////////////////////////	
	private final static String CONTENT = "content";
	private final static String NODE = "node";
	private final static String NODE_ID = "id";
	private final static String NODE_TYPE = "type";
	private final static String NODE_NAME = "name";
	private final static String NODE_DBID = "dbid";
	private final static String NODE_PARENTID = "parentid";
	private final static String NODE_HASCHILD = "haschild";
	private final static String NODE_X = "x";
	private final static String NODE_Y = "y";
	private final static String NODE_WIDTH = "width";
	private final static String NODE_HEIGHT = "height";

	private final static String NODE_FEATURES = "features";
	private final static String NODE_FEATURE_PROT = "port";
	private final static String NODE_FEATURE_NAME = "name";
	private final static String NODE_FEATURE_TYPE = "type";

	private final static String NODE_PROPERTIES = "properties";
	private final static String NODE_PROPERTIES_PROPERTY = "property";
	private final static String NODE_PROPERTIES_NAME = "name";
	private final static String NODE_PROPERTIES_VALUE = "value";

	private final static String LINK = "link";
	private final static String LINK_SOURCEID = "sourceid";
	private final static String LINK_SOURCEPORT = "sourceport";
	private final static String LINK_TAEGETID = "targetid";
	private final static String LINK_TARGETPORT = "targetport";
	private final static String LINK_TYPE = "type";

	private final static String SYSTEM_COMPLETE = "complete";

	public List<AADLNode> parseAADLToNode(Document document) {
		try {
			Element rootElm = document.getRootElement();
			if (rootElm.getName().equals(CONTENT)) {
				// 解析所有的node
				List<Element> nodes = rootElm.elements(NODE);
				List<AADLNode> nodeList = new ArrayList<AADLNode>();
				for (Iterator<Element> it = nodes.iterator(); it.hasNext();) {
					Element element = (Element) it.next();
					AADLNode node = new AADLNode();
					// node的属性
					List<Element> items = element.elements();
					for (int i = 0; i < items.size(); i++) {
						Element item = items.get(i);
						if (item.getName().equals(NODE_ID)) {
							node.setId(item.getTextTrim());
						} else if (item.getName().equals(NODE_TYPE)) {
							node.setType(item.getTextTrim());
						} else if (item.getName().equals(NODE_NAME)) {
							node.setName(item.getTextTrim());
						} else if (item.getName().equals(NODE_DBID)) {
							String temp = item.getTextTrim();
							if (temp != null && !temp.equals("")) {
								node.setDb_id(Long.parseLong(temp));
							}
						} else if (item.getName().equals(NODE_PARENTID)) {
							node.setParent_id(item.getTextTrim());
						} else if (item.getName().equals(NODE_HASCHILD)) {
							String temp = item.getTextTrim();
							if (temp != null && !temp.equals("")) {
								node.setHasChild(Boolean.parseBoolean(temp));
							}
						} else if (item.getName().equals(NODE_X)) {
							String temp = item.getTextTrim();
							if (temp != null && !temp.equals("")) {
								node.setX(Integer.parseInt(temp));
							}
						} else if (item.getName().equals(NODE_Y)) {
							String temp = item.getTextTrim();
							if (temp != null && !temp.equals("")) {
								node.setY(Integer.parseInt(temp));
							}
						} else if (item.getName().equals(NODE_WIDTH)) {
							String temp = item.getTextTrim();
							if (temp != null && !temp.equals("")) {
								node.setWidth(Integer.parseInt(temp));
							}
						} else if (item.getName().equals(NODE_HEIGHT)) {
							String temp = item.getTextTrim();
							if (temp != null && !temp.equals("")) {
								node.setHeight(Integer.parseInt(temp));
							}
						}// node的feature属性
						else if (item.getName().equals(NODE_FEATURES)) {
							List<Element> links = item
									.elements(NODE_FEATURE_PROT);
							List<AADLFeature> featureList = new ArrayList<AADLFeature>();
							// node的feature单项属性
							for (Iterator<Element> itLink = links.iterator(); itLink
									.hasNext();) {
								Element elementLink = (Element) itLink.next();
								AADLFeature feature = new AADLFeature();
								List<Element> properties = elementLink
										.elements();
								for (int j = 0; j < properties.size(); j++) {
									Element linkProperty = properties.get(j);
									if (linkProperty.getName().equals(
											NODE_FEATURE_NAME)) {
										feature.setName(linkProperty
												.getTextTrim());
									} else if (linkProperty.getName().equals(
											NODE_FEATURE_TYPE)) {
										feature.setType(parseFeatureType(linkProperty
												.getTextTrim()));
									}
								}// end port
								featureList.add(feature);
							}// end feature
							node.setFeatures(featureList);
						}// end else if-->features
							// node的properties属性
						else if (item.getName().equals(NODE_PROPERTIES)) {
							List<Element> pros = item
									.elements(NODE_PROPERTIES_PROPERTY);
							List<AADLProperty> propertyList = new ArrayList<AADLProperty>();
							// node的property单项属性
							for (Iterator<Element> itLink = pros.iterator(); itLink
									.hasNext();) {
								Element elementLink = (Element) itLink.next();
								List<Element> properties = elementLink
										.elements();
								String name = "";
								String value = "";
								for (int j = 0; j < properties.size(); j++) {
									Element linkProperty = properties.get(j);
									if (linkProperty.getName().equals(
											NODE_PROPERTIES_NAME)) {
										name = linkProperty.getTextTrim();
									} else if (linkProperty.getName().equals(
											NODE_PROPERTIES_VALUE)) {
										value = linkProperty.getTextTrim();
									}
								}// end property
								propertyList.add(new AADLProperty(name, value));
							}// end property
							node.setProperties(propertyList);
						}// end else if-->properties
					}// end所有的属性
					nodeList.add(node);
				}
				return nodeList;
			} else {
				return null;
			}
		} catch (Exception e) {
			// TODO: handle exception
			e.printStackTrace();
		}

		return null;
	}

	private String parseFeatureType(String imgType) {
		if (imgType.equals("In Data Port")) {
			return "in data port";
		} else if (imgType.equals("Out Data Port")) {
			return "out data port";
		} else if (imgType.equals("InOut Data Port")) {
			return "in out data port";
		} else if (imgType.equals("In Event Port")) {
			return "in event port";
		} else if (imgType.equals("Out Event Port")) {
			return "out event port";
		} else if (imgType.equals("InOut Event Port")) {
			return "in out event port";
		} else if (imgType.equals("In DataEvent Port")) {
			return "in event data port";
		} else if (imgType.equals("Out DataEvent Port")) {
			return "out event data port";
		} else if (imgType.equals("InOut DataEvent Port")) {
			return "in out event data port";
		} else if (imgType.equals("Requires Data Access")) {
			return "requires data access";
		} else if (imgType.equals("Provides Data Access")) {
			return "provides data access";
		} else if (imgType.equals("Requires Bus Access")) {
			return "requires bus access";
		} else if (imgType.equals("Provides Bus Access")) {
			return "provides bus access";
		}
		return "";
	}
	
	private String parseImplType(String type) {
		if (type.equals("bus")) {
			return "busImpl";
		} else if (type.equals("system")) {
			return "systemImpl";
		} else if (type.equals("device")) {
			return "deviceImpl";
		} else if (type.equals("memory")) {
			return "memoryImpl";
		} else if (type.equals("processor")) {
			return "processorImpl";
		} else if (type.equals("process")) {
			return "processImpl";
		} else if (type.equals("thread")) {
			return "threadImpl";
		} 
		return "";
	}
	
	private String parseDefineType(String type) {
		if (type.equals("bus")) {
			return "busType";
		} else if (type.equals("system")) {
			return "systemType";
		} else if (type.equals("device")) {
			return "deviceType";
		} else if (type.equals("processor")) {
			return "processorType";
		} else if (type.equals("memory")) {
			return "memoryType";
		} else if (type.equals("process")) {
			return "processType";
		} else if (type.equals("thread")) {
			return "threadType";
		} 
		return "";
	}
	
	private String parseConnectionType(String type) {
		if (type.equals("busAccessConnection")) {
			return "busAccess";
		}else if (type.equals("dataConnection")) {
			return "dataPort";
		}
		return "";
	}
	
	private String parseSubComponentType(String type) {
		if (type.equals("bus")) {
			return "busSubcomponent";
		}else if (type.equals("device")) {
			return "deviceSubcomponent";
		}else if (type.equals("process")) {
			return "processSubcomponent";
		}else if (type.equals("processor")) {
			return "processorSubcomponent";
		}else if (type.equals("system")) {
			return "systemSubcomponent";
		}else if (type.equals("memory")) {
			return "memorySubcomponent";
		}else if (type.equals("thread")) {
			return "threadSubcomponent";
		}
		return "";
	}
	
	
	public AAXLFeature parseFeatureTypeToAAXL(String imgType) {
		if (imgType.equals("in data port")) {
			return new AAXLFeature(DATA_PORT);
		} else if (imgType.equals("out data port")) {
			return new AAXLFeature(DATA_PORT, DIRECTION_OUT);
		} else if (imgType.equals("in out data port")) {
			return null;
		} else if (imgType.equals("in event port")) {
			return null;
		} else if (imgType.equals("out event port")) {
			return null;
		} else if (imgType.equals("in out event port")) {
			return null;
		} else if (imgType.equals("in event data port")) {
			return null;
		} else if (imgType.equals("out event data port")) {
			return null;
		} else if (imgType.equals("in out event data port")) {
			return null;
		} else if (imgType.equals("requires data access")) {
			return null;
		} else if (imgType.equals("provides data access")) {
			return null;
		} else if (imgType.equals("requires bus access")) {			
			return new AAXLFeature(BUS_ACCESS, REQUIRED);		
		} else if (imgType.equals("provides bus access")) {
			return new AAXLFeature(BUS_ACCESS);	
		}
		return null;
	}

	public List<AADLNode> parseAADLToNode(String xml) {
		try {
			Document document = DocumentHelper.parseText(xml);
			return parseAADLToNode(document);
		} catch (Exception e) {
			// TODO: handle exception
			e.printStackTrace();
		}
		return null;
	}

	public List<AADLNode> parseAADLToNode(File inputXml) {
		try {
			SAXReader saxReader = new SAXReader();
			Document document = saxReader.read(inputXml);
			return parseAADLToNode(document);
		} catch (Exception e) {
			// TODO: handle exception
			e.printStackTrace();
		}
		return null;
	}

	public List<AADLLink> parseAADLToLink(String xml) {
		try {
			Document document = DocumentHelper.parseText(xml);
			return parseAADLToLink(document);
		} catch (Exception e) {
			// TODO: handle exception
			e.printStackTrace();
		}
		return null;
	}

	public List<AADLLink> parseAADLToLink(File inputXml) {
		try {
			SAXReader saxReader = new SAXReader();
			Document document = saxReader.read(inputXml);
			return parseAADLToLink(document);
		} catch (Exception e) {
			// TODO: handle exception
			e.printStackTrace();
		}
		return null;
	}

	public List<AADLLink> parseAADLToLink(Document document) {
		try {
			Element rootElm = document.getRootElement();
			if (rootElm.getName().equals(CONTENT)) {
				// 解析所有的link
				List<Element> links = rootElm.elements(LINK);
				List<AADLLink> linkList = new ArrayList<AADLLink>();
				for (Iterator it = links.iterator(); it.hasNext();) {
					Element elm = (Element) it.next();
					List<Element> items = elm.elements();
					AADLLink aadlLink = new AADLLink();
					for (int j = 0; j < items.size(); j++) {
						Element linkProperty = items.get(j);

						if (linkProperty.getName().equals(LINK_SOURCEID)) {
							aadlLink.setSourceId(linkProperty.getTextTrim());
						} else if (linkProperty.getName().equals(
								LINK_SOURCEPORT)) {
							aadlLink.setSourcePort(linkProperty.getTextTrim());
						} else if (linkProperty.getName().equals(LINK_TAEGETID)) {
							aadlLink.setTargetId(linkProperty.getTextTrim());
						} else if (linkProperty.getName().equals(
								LINK_TARGETPORT)) {
							aadlLink.setTargetPort(linkProperty.getTextTrim());
						} else if (linkProperty.getName().equals(LINK_TYPE)) {
							aadlLink.setType(linkProperty.getTextTrim());
						}

					}
					linkList.add(aadlLink);
				}
				return linkList;
			} else {
				return null;
			}
		} catch (Exception e) {
			// TODO: handle exception
			e.printStackTrace();
		}

		return null;
	}
	
	public void parseAAXL(String xml,String path,String projectName) {
		List<AADLNode> nodeList = parseAADLToNode(xml);
		List<AADLLink> linkList = parseAADLToLink(xml);
		Map<String, AADLNode> searchMap = new HashMap<String, AADLNode>();
		Map<String, AAXLElement> nameMap = new HashMap<String, AAXLElement>();
		
		// 系统默认添加complete system
		AAXLElement complete = new AAXLElement();
		// 处理名称
		complete.setName(SYSTEM_COMPLETE);
		// 处理类型
		complete.setType("system");
		nameMap.put(SYSTEM_COMPLETE, complete);
		
		for (int i = 0; i < nodeList.size(); i++) {
			searchMap.put(nodeList.get(i).getId(), nodeList.get(i));
			AAXLElement element = new AAXLElement();
			nameMap.put(nodeList.get(i).getName(), element);
			/*// device类型，默认内嵌process
			if (nodeList.get(i).getType().trim().toLowerCase().equals("device")) {
				AAXLElement process = new AAXLElement();
				process.setType("process");
				nameMap.put(nodeList.get(i).getName() + "_process", process);
			}*/
		}

		// 遍历nodelist构建aadlElement
		for (int i = 0; i < nodeList.size(); i++) {
			AADLNode node = nodeList.get(i);
			if (node.isHasChild()) {
				continue;
			} else {
				AAXLElement element = nameMap.get(node.getName());
				// 处理名称
				element.setName(node.getName());
				// 处理类型
				element.setType(node.getType().trim().toLowerCase());
				
				// 处理features
				if (node.getFeatures() != null) {
					Set<AAXLFeature> features = new HashSet<AAXLFeature>();
					for (int j = 0; j < node.getFeatures().size(); j++) {
						AADLFeature feature = node.getFeatures().get(j);
						AAXLFeature myfeature = parseFeatureTypeToAAXL(feature.getType());
						myfeature.setName(feature.getName());
						features.add(myfeature);
					}
					element.setFeatures(features);
				}
				//to-do
//				// 处理properties
//				if (node.getProperties() != null) {
//					Set<ContentPair> properties = new HashSet<ContentPair>();
//					for (int j = 0; j < node.getProperties().size(); j++) {
//						AADLProperty property = node.getProperties().get(j);
//						ContentPair pair = new ContentPair(property.getName(),
//								property.getValue());
//						properties.add(pair);
//					}
//					element.setProperties(properties);
//				}
				// 处理parent
				String parentId = node.getParent_id();
				AAXLElement parentElement;
				if (parentId != null && !parentId.equals("")
						&& !parentId.equals("null")) {
					parentElement = nameMap.get(searchMap.get(parentId)
							.getName());
				} else {
					parentElement = nameMap.get(SYSTEM_COMPLETE);
				}
				//////////////////////不能移植全部的subcomponent//////////////////////////////
			/*	if (parentElement.getType().equals("device") && node.getType().endsWith("thread")) {
					parentElement = nameMap.get(searchMap.get(parentId)
							.getName() + "_process");
				}*/
				
				AAXLSubComponent subComponent = new AAXLSubComponent();
				subComponent.setType(parseSubComponentType(node.getType()));
				subComponent.setName(node.getName());
				subComponent.setClassifier("/aadlSpec[@name="+projectName+"]/"+parseImplType(node.getType())+"[@name="+node.getName()+"_aadl."+node.getName()+"]");
				if (parentElement.getComponents() == null) {
					Set<AAXLSubComponent> subcomponents = new HashSet<AAXLSubComponent>();
					parentElement.setComponents(subcomponents);
				}
				parentElement.getComponents().add(subComponent);

				/*// device类型，默认内嵌process
				if (node.getType().trim().toLowerCase().equals("device")) {
					String name = node.getName() + "_process";
					AAXLElement process = nameMap.get(name);
					// 处理名称
					process.setName(name);
					// 处理类型
					process.setType("process");
					//////////////////////移植全部的feature会有问题//////////////////////////////
					process.setFeatures(element.getFeatures());
					
					AAXLSubComponent processSubComponent = new AAXLSubComponent();
					processSubComponent.setType(parseSubComponentType("process"));
					processSubComponent.setName(node.getName()+"_process");
					processSubComponent.setClassifier("/aadlSpec[@name="+projectName+"]/"+parseImplType("process")+"[@name="+node.getName()+"_process_aadl."+node.getName()+"_process]");
					AAXLElement device = nameMap.get(node.getName());
					if (device.getComponents() == null) {
						Set<AAXLSubComponent> subcomponents = new HashSet<AAXLSubComponent>();
						device.setComponents(subcomponents);
					}
					device.getComponents().add(processSubComponent);
				}*/
			}
		}
		// 遍历linkList填充aaxlElement的connections
		int dataIndex = 0;
		int busAccessIndex = 0;
		int eventIndex = 0;
		int dataEventIndex = 0;
		int dataAccessIndex = 0;
		for (int i = 0; i < linkList.size(); i++) {
			AADLLink link = linkList.get(i);
			String sourceid = link.getSourceId();
			String sourcePort = link.getSourcePort();
			String targetid = link.getTargetId();
			String targetPort = link.getTargetPort();
			
			AAXLConnection connection = new AAXLConnection();
			AAXLConnection device = new AAXLConnection();
			
			String temp = sourcePort + " " + targetPort;
			if (temp.contains("In Data:") || temp.contains("Out Data:")
					|| temp.contains("InOut Data:")) {
				dataIndex++;
				connection.setName("DataConnection" + dataIndex);
				connection.setType("dataConnection");
			} else if (temp.contains("Requires Bus:")
					|| temp.contains("Provides Bus:")) {
				busAccessIndex++;
				connection.setName("BusAccessConnection" + busAccessIndex);
				connection.setType("busAccessConnection");
			} else if (temp.contains("In Event:")
					|| temp.contains("Out Event:")
					|| temp.contains("InOut Event:")) {
				
			} else if (temp.contains("In DataEvent:")
					|| temp.contains("Out DataEvent:")
					|| temp.contains("InOut DataEvent:")) {
				
			} else if (temp.contains("Requires Data:")
					|| temp.contains("Provides Data:")) {
				
			}
			
			String elementId = targetid;
			boolean deviceFlag = false;
			// same level
			if ((searchMap.get(sourceid).getParent_id() == null && searchMap
					.get(targetid).getParent_id() == null)
					|| searchMap.get(sourceid).getParent_id()
							.equals(searchMap.get(targetid).getParent_id())) {
				//父节点id
				elementId = searchMap.get(sourceid).getParent_id();
				AADLNode parentNode = searchMap.get(elementId);
				if (parentNode == null) {
					parentNode = new AADLNode();
					parentNode.setName(SYSTEM_COMPLETE);
					parentNode.setType("system");
				}
				AADLNode sourceNode = searchMap.get(sourceid);
				String srcName = sourceNode.getName();
				
				String sourcePortName = "";
				if (sourcePort.contains(":")) {   //--->type
					sourcePortName = sourcePort.split(":")[1];
					//---to-do
					connection.src = "/aadlSpec[@name="+projectName+"]/"+parseDefineType(sourceNode.getType())+"[@name="+sourceNode.getName()+"_aadl]"+
							"]/features/"+parseConnectionType(connection.getType())+"[@name="+sourcePortName+"]";
					connection.srcContext = "/aadlSpec[@name="+projectName+"]/"+parseImplType(parentNode.getType())+"[@name="+parentNode.getName()+"_aadl."+parentNode.getName()+
							"]/subcomponents/"+parseSubComponentType(sourceNode.getType())+"[@name="+srcName+"]";
				} else { // 直接与结点相连  //--->impl
					connection.src = "/aadlSpec[@name="+projectName+"]/"+parseImplType(parentNode.getType())+"[@name="+parentNode.getName()+"_aadl."+parentNode.getName()+
							"]/subcomponents/"+parseSubComponentType(sourceNode.getType())+"[@name="+srcName+"]";
				}
				
				AADLNode dstNode = searchMap.get(targetid);
				String dstName = searchMap.get(targetid).getName();
				if (targetPort.contains(":")) {  //--->type
					String targetPortName = targetPort.split(":")[1];
					connection.dst = "/aadlSpec[@name="+projectName+"]/"+parseDefineType(dstNode.getType())+"[@name="+dstNode.getName()+"_aadl]"+
							"]/features/"+parseConnectionType(connection.getType())+"[@name="+targetPortName+"]";
					connection.dstContext = "/aadlSpec[@name="+projectName+"]/"+parseImplType(parentNode.getType())+"[@name="+parentNode.getName()+"_aadl."+parentNode.getName()+
							"]/subcomponents/"+parseSubComponentType(dstNode.getType())+"[@name="+dstName+"]";
				}else {
					connection.dst = "/aadlSpec[@name="+projectName+"]/"+parseImplType(parentNode.getType())+"[@name="+parentNode.getName()+"_aadl."+parentNode.getName()+
							"]/subcomponents/"+parseSubComponentType(dstNode.getType())+"[@name="+dstName+"]";
				}
				
			}// targetid -->parent
			else if (searchMap.get(sourceid).getParent_id().equals(targetid)) {
				elementId = targetid;
				AADLNode srcNode = searchMap.get(sourceid);
				String srcName = searchMap.get(sourceid).getName();
				AADLNode dstNode = searchMap.get(targetid);
				String dstName = searchMap.get(targetid).getName();
				
				/*if (searchMap.get(targetid).getType().equals("device")&&searchMap.get(sourceid).getType().equals("thread")) {
					deviceFlag = true;
					device.type = connection.type;
					device.name = connection.name;
				}else {
					deviceFlag = false;	
				}*/
				//thread--device--process--connection--device
				String sourcePortName = "";
				if (sourcePort.contains(":")) {   //--->type
					sourcePortName = sourcePort.split(":")[1];
					String src = "/aadlSpec[@name="+projectName+"]/"+parseDefineType(srcNode.getType())+"[@name="+srcNode.getName()+"_aadl]"+
							"]/features/"+parseConnectionType(connection.getType())+"[@name="+sourcePortName+"]";
					String srcContext = "/aadlSpec[@name="+projectName+"]/"+parseImplType(dstNode.getType())+"[@name="+dstName+"_aadl."+dstName+
							"]/subcomponents/"+parseSubComponentType(srcNode.getType())+"[@name="+srcName+"]";
					/*if (deviceFlag) {
						device.src = src;
						device.srcContext = srcContext;
					}else {
						connection.src = src;
						connection.srcContext = srcContext;
					}*/
					
				} else { 
					// 直接与结点相连  //--->impl
					connection.src = "/aadlSpec[@name="+projectName+"]/"+parseImplType(srcNode.getType())+"[@name="+srcNode.getName()+"_aadl."+srcNode.getName()+
							"]/subcomponents/"+parseSubComponentType(srcNode.getType())+"[@name="+srcName+"]";									
				}				
							
				String targetPortName = targetPort.split(":")[1];
				/*if(deviceFlag){
					connection.src = device.dst = "/aadlSpec[@name="+projectName+"]/"+parseDefineType("process")+"[@name="+dstName+"_process_aadl]"+
								"]/features/"+parseConnectionType(connection.getType())+"[@name="+targetPortName+"]";
					connection.srcContext = device.dstContext = "/aadlSpec[@name="+projectName+"]/"+parseImplType("process")+"[@name="+dstName+"_process_aadl."+dstName+
								"_process]";
			
				}*/
				connection.dst = "/aadlSpec[@name="+projectName+"]/"+parseDefineType(dstNode.getType())+"[@name="+dstName+"_aadl]"+
							"]/features/"+parseConnectionType(connection.getType())+"[@name="+targetPortName+"]";
				connection.dstContext = "/aadlSpec[@name="+projectName+"]/"+parseImplType(dstNode.getType())+"[@name="+dstName+"_aadl."+dstName+
								"]";	
			}// sourceid -->parent
			else if (sourceid.equals(searchMap.get(targetid).getParent_id())) {
				elementId = sourceid;
				AADLNode srcNode = searchMap.get(sourceid);
				String srcName = searchMap.get(sourceid).getName();
				AADLNode dstNode = searchMap.get(targetid);
				String dstName = searchMap.get(targetid).getName();
				/*if (searchMap.get(sourceid).getType().equals("device")&&searchMap.get(targetid).getType().equals("thread")) {
					deviceFlag = true;
					device.type = connection.type;
					device.name = connection.name;
				}else {
					deviceFlag = false;	
				}*/
				//thread--device--process--connection--device
				String sourcePortName = sourcePort.split(":")[1];
				connection.src = "/aadlSpec[@name="+projectName+"]/"+parseDefineType(srcNode.getType())+"[@name="+srcName+"_aadl]"+
						"]/features/"+parseConnectionType(connection.getType())+"[@name="+sourcePortName+"]";
				connection.srcContext = "/aadlSpec[@name="+projectName+"]/"+parseImplType(srcNode.getType())+"[@name="+srcName+"_aadl."+srcName+
						"]";
		
				if (targetPort.contains(":")) {  //--->type
					String targetPortName = targetPort.split(":")[1];					
					/*if (deviceFlag) {
						//src必须要有port
						connection.dst = device.src = "/aadlSpec[@name="+projectName+"]/"+parseDefineType("process")+"[@name="+srcName+"_process_aadl]"+
								"]/features/"+parseConnectionType(connection.getType())+"[@name="+sourcePortName+"]";
						connection.dstContext = device.srcContext = "/aadlSpec[@name="+projectName+"]/"+parseImplType("process")+"[@name="+srcName+"_process_aadl."+srcName+
								"_process]";
						device.dst = "/aadlSpec[@name="+projectName+"]/"+parseDefineType("process")+"[@name="+dstName+"_aadl]"+
								"]/features/"+parseConnectionType(connection.getType())+"[@name="+targetPortName+"]";
						device.dstContext = "/aadlSpec[@name="+projectName+"]/"+parseImplType("process")+"[@name="+srcName+"_process_aadl."+srcName+
								"_process]/subcomponents/"+parseSubComponentType(dstNode.getType())+"[@name="+dstName+"]";
					}else{*/
						connection.dst = "/aadlSpec[@name="+projectName+"]/"+parseDefineType(dstNode.getType())+"[@name="+dstName+"_aadl]"+
								"]/features/"+parseConnectionType(connection.getType())+"[@name="+targetPortName+"]";
						connection.dstContext = "/aadlSpec[@name="+projectName+"]/"+parseImplType(srcNode.getType())+"[@name="+srcName+"_aadl."+srcName+
								"]/subcomponents/"+parseSubComponentType(dstNode.getType())+"[@name="+dstName+"]";
					/*}*/
					
				}else {
					connection.dst = "/aadlSpec[@name="+projectName+"]/"+parseImplType(srcNode.getType())+"[@name="+srcName+"_aadl."+srcName+
							"]/subcomponents/"+parseSubComponentType(dstNode.getType())+"[@name="+dstName+"]";
				}
			}
			
			AAXLElement parentElement = null;		
			AADLNode tempNode = searchMap.get(elementId);
			if (tempNode == null) {
				parentElement = nameMap.get(SYSTEM_COMPLETE);
			} else {
				parentElement = nameMap.get(tempNode.getName());
			}
			
			if (parentElement != null) {
				if (parentElement.getConnections() == null) {
					Set<AAXLConnection> connections = new HashSet<AAXLConnection>();
					parentElement.setConnections(connections);
				}
				parentElement.getConnections().add(connection);
				//需要处理device的process情况
				/*if (deviceFlag) {				
					parentElement = nameMap.get(searchMap.get(elementId)
							.getName() + "_process");
					if (parentElement.getConnections() == null) {
						Set<AAXLConnection> connections = new HashSet<AAXLConnection>();
						parentElement.setConnections(connections);
					}
					parentElement.getConnections().add(device);
				}*/
			}
		}
		
		Set<AAXLElement> result = new HashSet<AAXLElement>(nameMap.values());
		
		Document document = DocumentHelper.createDocument();
		Element root = document.addElement(CORE);
		root.addAttribute(XMI_VERSION, "2.0");
		root.addAttribute(XMLNS_XMI, "http://www.omg.org/XMI");
		root.addAttribute(XMLNS_XSI, "http://www.w3.org/2001/XMLSchema-instance");
		root.addAttribute(XMLNS_CORE, "http:///AADL/core");
		root.addAttribute(XMLNS_PROPERTY, "http:///AADL/property");
		root.addAttribute(NAME, projectName);
		//默认添加的element
//		Element completeType = root.addElement(SYSTEM_TYPE);
//		completeType.addAttribute(NAME, SYSTEM_COMPLETE+"_aadl");
//		Element completeImpl = root.addElement(SYSTEM_IMPL);
//		completeImpl.addAttribute(NAME, SYSTEM_COMPLETE+"_aadl");
		for (AAXLElement element:  result) {
			 Element type = root.addElement(parseDefineType(element.getType()));
			 type.addAttribute(NAME, element.getName()+"_aadl");
			 if (element.getFeatures() != null && element.getFeatures().size() > 0) {
				 Element features = type.addElement(FEATURES);
				for (AAXLFeature feature : element.getFeatures()) {
					Element feaElement = features.addElement(feature.getType());
					feaElement.addAttribute(NAME, feature.getName());
					if (feature.getDirection() != null && !feature.getDirection().equals("")) {
						feaElement.addAttribute(DIRECTION, feature.getDirection());
					}
				}
			}
			 
			Element impl = root.addElement(parseImplType(element.getType()));
			impl.addAttribute(NAME, element.getName()+"_aadl."+element.getName());
			impl.addAttribute(COMP_TYPE, "/aadlSpec[@name="+projectName+"]/"+parseDefineType(element.getType())+"[@name="+element.getName()+"_aadl]");
			if (element.getComponents() != null && element.getComponents().size() > 0) {
				 Element subComponent = impl.addElement(SUB_COMPONENTS);
				for (AAXLSubComponent component : element.getComponents()) {
					Element comElement = subComponent.addElement(component.getType());
					comElement.addAttribute(NAME, component.getName());
					comElement.addAttribute(CLASSIFIER, component.getClassifier());
				}
			}
			if (element.getConnections()!= null && element.getConnections().size() > 0) {
				Element connections = impl.addElement(CONNECTIOINS);
				for (AAXLConnection connection : element.getConnections()) {
					Element conElement = connections.addElement(connection.getType());
					conElement.addAttribute(NAME, connection.getName());
					if (connection.getDstContext() != null && !connection.getDstContext().equals("")) {
						conElement.addAttribute(DST_CONTEXT, connection.getDstContext());
					}
					if (connection.getSrcContext() != null && !connection.getSrcContext().equals("")) {
						conElement.addAttribute(SRC_CONTEXT, connection.getSrcContext());
					}
					conElement.addAttribute(DST, connection.getDst());
					conElement.addAttribute(SRC, connection.getSrc());
				}
			}
		}
		
		try {
			File file = getFile(path);
			FileWriter fWriter = null;
			try {
				fWriter = new FileWriter(file);
				fWriter.write(document.asXML());
			} finally {
				fWriter.flush();
				fWriter.close();
			}
		} catch (Exception e) {
			// TODO: handle exception
			e.printStackTrace();
		}
	}

	protected File getFile(String targetFileName) throws IOException {
		File targetFile = new File(targetFileName);
		if (!targetFile.getParentFile().exists()) {
			targetFile.getParentFile().mkdirs();
		}
		if (!targetFile.exists()) {
			targetFile.createNewFile();
		}
		return targetFile;
	}
}
